#!/usr/bin/env python3

from urllib.request import urlretrieve
import argparse
import json
import os
import re
import shutil, shlex
import subprocess
import sys
import tarfile
from pygit2 import Repository

import pathlib
for d in pathlib.Path(__file__).resolve().parents:
  if os.path.exists(os.path.join(d, 'behave.ini')):
    ROOT = d
    break
os.chdir(ROOT)
# because behave doesn't think it's useful to be able to load local stuff... oy...
sys.path.insert(0, os.path.abspath('test/features/steps'))

def load_json(path, default):
  try:
    with open(path) as f:
      return json.load(f)
  except:
    return default
class BooleanAction(argparse.Action):
  def __init__(self, option_strings, dest, nargs=None, **kwargs):
    super().__init__(option_strings, dest, nargs=0, **kwargs)

  def __call__(self, parser, namespace, values, option_string=None):
    setattr(namespace, self.dest, not option_string.startswith('--no'))
class ClientAction(argparse.Action):
  def __init__(self, option_strings, dest, nargs=None, **kwargs):
    super().__init__(option_strings, dest, nargs=0, **kwargs)

  def __call__(self, parser, namespace, values, option_string=None):
    print(type(input_string), type(values))
    if option_string == '--jurism' and type(values) == bool and values:
      setattr(namespace, self.dest, 'jurism')
    elif option_string == '--jurism' and type(values) == bool and not values:
      setattr(namespace, self.dest, 'zotero')
    elif option_string == '--client' and type(values) == str and values in ['zotero', 'jurism']:
      setattr(namespace, self.dest, values)
    else:
      raise ValueError(f'Unexpected argument {option_string} = {values}')
parser = argparse.ArgumentParser()
parser.add_argument('--stop', '--no-stop', dest='stop', action=BooleanAction, default=(os.environ.get('CI') != 'true'))
parser.add_argument('--jurism', dest='client', action='store_const', const='jurism', default=os.environ.get('CLIENT', 'zotero'))
parser.add_argument('--client', dest='client', default=os.environ.get('CLIENT', 'zotero'))
parser.add_argument('--beta', action='store_true')
parser.add_argument('--keep', '--no-keep', dest='keep', action=BooleanAction, default=False)
parser.add_argument('--workers', '--no-workers', dest='workers', action=BooleanAction, default=True)
parser.add_argument('--this', action='store_true')
parser.add_argument('--test-this', action='store_true')
parser.add_argument('--slow', action='store_true',
  default = os.environ.get('TRAVIS_BRANCH') in load_json(os.path.join(ROOT, '.slow.json'), []) or
            os.environ.get('TRAVIS_BRANCH') == 'master' or
            '#slow' in os.environ.get('TRAVIS_COMMIT_MESSAGE', '') or
            os.environ.get('TRAVIS_EVENT_TYPE') == 'cron' or
            os.environ.get('TRAVIS_TAG', '') != ''
)
parser.add_argument('--test')
parser.add_argument('--balance')
parser.add_argument('--tagged', action='store_true', default=os.environ.get('TRAVIS_TAG', '') != '')
parser.add_argument('--nightly', action='store_true',
  default=os.environ.get('TRAVIS_EVENT_TYPE') == 'cron' or '#nightly' in os.environ.get('TRAVIS_COMMIT_MESSAGE', '')
)
args, unknownargs = parser.parse_known_args()
sys.argv = sys.argv[:1] + unknownargs

if args.balance is None: # local run
  process = subprocess.Popen(['npm', 'run', 'build'], stdout=subprocess.PIPE)
  while True:
    line = process.stdout.readline()
    print(line.decode('utf-8'), end='')
    if process.poll() is not None: break
  returncode = process.poll()
  if returncode != 0:
    print(f'Build exited with exit code {returncode}')
    sys.exit(returncode)

if args.nightly and args.balance and not args.tagged: # test for beta on nightly
  args.beta = (args.balance == '2')
  args.balance = None

if args.this or args.test_this:
  repo = Repository('.')
  branch = repo.head.name.split('/')[-1]
  assert re.match(r'^gh-[0-9]+$', branch)
  if args.this: args.this = branch.replace('gh-', '@')
  if args.test_this: args.test = branch.replace('gh-', '')

if args.test or args.this or args.nightly or args.tagged or args.beta: args.slow = True

if args.client == 'jurism' and args.beta and 'CI' in os.environ:
  print(f"********* SKIPPING{' BETA' if args.beta else ''} BUILD FOR {args.client.upper()} UNTIL FURTHER NOTICE ****************")
  sys.exit()

print(args)
sys.argv.extend(['--define', f"client={args.client}"])
sys.argv.extend(['--define', f'workers={str(args.workers).lower()}'])
if args.balance: sys.argv.extend(['--define', f"balance={args.balance}"])
sys.argv.extend(['--define', f'kill={str(not args.keep).lower()}'])
if args.stop: sys.argv.append('--stop')
if args.slow: sys.argv.extend(['--define', 'slow=true'])
if args.beta: sys.argv.extend(['--define', f'beta=true'])
if args.test: sys.argv.extend(['--define', f'test={args.test}'])
if args.this: sys.argv.extend(['--tags', args.this ])
print(' '.join(sys.argv))

# *no* idea
def cleanup():
  if os.path.exists('travis.output'): os.remove('travis.output')
import atexit
atexit.register(cleanup)

#https://stackoverflow.com/questions/28829350/run-python-behave-from-python-instead-of-command-line
from behave.__main__ import Configuration, run_behave
sys.exit(run_behave(Configuration(None)))
